<?php

namespace Library\Https;

use Library\Components\Base;
use Library\Exceptions\NotFundException;

class Request extends Base
{
    private $method;

    /**
     * 获取请求方法
     */
    public function getMethod()
    {
        if (isset($_SERVER['REQUEST_METHOD'])) {
            return strtoupper($_SERVER['REQUEST_METHOD']);
        }
        return 'GET';
    }

    /**
     * 获取请求头
     * @param $name
     * @param null $defaultValue
     * @return mixed|null
     */
    public function getHeader($name, $defaultValue = null)
    {
        $name = ucfirst($name);
        /**
         * 获取请求头的方式nginx和apache不同
         * apache中可以使用apache_request_headers
         * nginx中可以使用$_SERVER 并且需要注意的是的是自定义信息等参数会在前面自动加上 HTTP_，并且会转换为大写
         */
        if (function_exists("apache_request_headers")) {
            $headers = apache_request_headers();
            return $headers[$name] ?? $defaultValue;
        }
        $name = strtoupper($name);
        return $_SERVER[$name] ?? $defaultValue;
    }

    /**
     * get参数数组
     * @var array
     */
    private $queryParams = [];

    /**
     * 获取get参数
     * @param null $name
     * @param null $defaultValue
     * @return array|mixed|null
     */
    public function get($name = null, $defaultValue = null)
    {
        if ($name === null) {
            return $this->getQueryParams();
        }
        return $this->getQueryParam($name, $defaultValue);
    }

    public function getQueryParam($name, $defaultValue = null)
    {
        $params = $this->getQueryParams();
        return $params[$name] ?? $defaultValue;
    }

    /**
     * post参数数组
     */
    private $bodyParams = [];

    /**
     * 获取所有参数
     * @return array
     */
    public function getQueryParams()
    {
        if (empty($this->queryParams)) {
            $this->queryParams = $_GET;
        }
        return $this->queryParams;
    }

    /**
     * 获取post参数
     * @param null $name
     * @param null $defaultValue
     * @return array|mixed|null
     */
    public function post($name = null, $defaultValue = null)
    {
        if ($name === null) {
            return $this->getBodyParams();
        }
        return $this->getBodyParam($name, $defaultValue);
    }

    public function getBodyParam($name, $defaultValue = null)
    {
        $params = $this->getBodyParams();
        if (is_object($params)) {
            try {
                return $params->{$name};
            } catch (\Exception $e) {
                return $defaultValue;
            }
        }
        return $params[$name] ?? $defaultValue;
    }

    /**
     * 获取POST所有参数
     * @return array
     */
    public function getBodyParams()
    {
        $contentType = strtolower($this->getHeader("Content-Type"));
        if (strpos($contentType, "multipart/form-data") === false) {  // 如果使用表单提交
            $this->bodyParams = $_POST;
        } else {
            $this->bodyParams = json_decode(file_get_contents("php://input"), true);
        }
        return $this->bodyParams ?? [];
    }


    private $route;

    /**
     * 控制器处理
     * @param $route
     * @return mixed
     * @throws NotFundException
     */
    public function runAction($route, $defaultRoute=true)
    {
        if (array_key_exists($route, $this->route)) {  // 判断是否定义该路由
            $route = $this->route[$route];
        } else if (!$defaultRoute) {
            throw new NotFundException("route not found:" . $route);
        }

        $match = explode("/", $route);
        $match = array_filter($match);

        // 处理$route=/
        if (empty($match)) {
            $match = ['index'];
            $controller = $this->createController($match);
            $action = "index";
        } else if (count($match) < 2) {
            $controller = $this->createController($match);
            $action = "index";
        } else {
            $action = array_pop($match);  // 返回数组最后一个value
            $controller = $this->createController($match);

            if (!method_exists($controller, $action)) {
                throw new NotFundException("method not found: ".$action);
            }
        }

        // 将get, post注入到控制器方法中
        return $controller->$action(array_merge($this->getQueryParams(), $this->getBodyParams()));
    }

    // app应用控制器命名空间
    private $controllerNameSpace = "App\\Https\\Controllers\\";

    // 之前定义的基类控制器
    private $baseController = "Library\\Https\\Controller";

    /**
     * @param $match
     * @return mixed 返回的是一个控制器的路径
     * @throws NotFundException
     */
    public function createController($match)
    {
        $controllerName = $this->controllerNameSpace;

        foreach ($match as $namespace) {
            $controllerName .= ucfirst($namespace) . "\\";
        }

        $controllerName = rtrim($controllerName, "\\") . "Controller";

        if (!class_exists($controllerName)) { // 如果不存在该控制器
            if ($controllerName == $this->controllerNameSpace . "IndexController") {
                return new $this->baseController;
            }
            throw new NotFundException("controller nout found: ".$controllerName);
        }

        return new $controllerName;
    }

    public function resolve($route)
    {
        $this->route = $route;  // 把路由列表存进来
        return $this->getPathUrl();
    }

    private $pathUrl;

    /**
     * 获取请求地址
     * @return false|string
     */
    public function getPathUrl()
    {
        if (is_null($this->pathUrl)) {
            $url = trim($_SERVER["REQUEST_URI"], "/");
            $index = strpos($url, "?");
            $this->pathUrl = ($index > -1) ? substr($url, 0, $index) : $url;
        }

        return $this->pathUrl;
    }
}